﻿#region Using directives
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Web.Script.Services;
using System.Web.Services;

#endregion

namespace ProcolServices {
    /// <summary>
    /// Summary description for UpdateService
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [ToolboxItem(false)]
    [ScriptService]
    public class UpdateService : WebService {
        private readonly ProcolDataContext db = new ProcolDataContext();

        [WebMethod]
        public UpdateHolder[] GetSystemUpdates() {
            var query = from u in db.SystemUpdates
                        orderby u.Timestamp descending 
                        select new UpdateHolder(u.UpdateId, u.EntryId, -1, u.Origin, u.Target, u.Timestamp); ;

            return query.ToArray();
        }

        [WebMethod]
        public UpdateHolder[] GetIdeaUpdates(int uid, int ideaId) {
            if (ideaId < 0) {
                var query = from u in db.IdeaUpdates
                            where (u.Origin == uid || u.Target == uid)
                            orderby u.Timestamp descending 
                            select new UpdateHolder(u.UpdateId, u.EntryId, u.IdeaId, u.Origin, u.Target, u.Timestamp);

                return query.ToArray();
            }

            var query2 = from u in db.IdeaUpdates
                         where (u.Origin == uid || u.Target == uid) && u.IdeaId == ideaId
                         orderby u.Timestamp descending 
                         select new UpdateHolder(u.UpdateId, u.EntryId, u.IdeaId, u.Origin, u.Target, u.Timestamp);

            return query2.ToArray();
        }

        [WebMethod]
        public UpdateHolder[] GetProjectUpdates(int uid, int projectId) {
            if (projectId < 0) {
                var query = from u in db.ProjectUpdates
                            where (u.Origin == uid || u.Target == uid)
                            orderby u.Timestamp descending 
                            select new UpdateHolder(u.UpdateId, u.EntryId, u.ProjectId, u.Origin, u.Target, u.Timestamp);

                return query.ToArray();
            }

            var query2 = from u in db.ProjectUpdates
                         where (u.Origin == uid || u.Target == uid) && u.ProjectId == projectId
                         orderby u.Timestamp descending 
                         select new UpdateHolder(u.UpdateId, u.EntryId, u.ProjectId, u.Origin, u.Target, u.Timestamp);

            return query2.ToArray();
        }

        [WebMethod]
        public UpdateHolder[] GetMembersUpdates(int uid) {
            var output = new List<UpdateHolder>();
            var stack = new List<int>();

            foreach (var users in GetFellowUserIds(uid)) {
                foreach (var fellowId in users.Where(u => !stack.Contains(u))) {
                    var projectUpdates = from u in GetProjectUpdates(fellowId, -1)
                                         orderby u.Timestamp descending 
                                         select u;

                    var ideaUpdates = from u in GetIdeaUpdates(fellowId, -1)
                                      orderby u.Timestamp descending 
                                      select u;

                    foreach (var p in projectUpdates)
                        output.Add(p);

                    foreach (var i in ideaUpdates)
                        output.Add(i);

                    stack.Add(fellowId);
                }
            }

            return output.OrderByDescending(p => p.Timestamp).ToArray();
        }

        private IQueryable<IQueryable<int>> GetFellowUserIds(int uid) {

            var userType = (from i in db.Users
                            where i.UserId == uid
                            select i).Single();
            if (userType.Role == 0)
            {

                return (from t in db.UserTeams
                        let teams = (from u in db.UserTeams
                                     where u.UserId == uid
                                     select u.TeamId)
                        let fellowUsers = (from x in db.UserTeams
                                           where teams.Contains(x.TeamId) && x.UserId != uid
                                           select x.UserId)
                        select fellowUsers).Distinct();
            }

            return (from t in db.UserTeams
                    let teams = (from u in db.Teams
                                 where u.TutorId == uid
                                 select u.TeamId)
                    let fellowUsers = (from x in db.UserTeams
                                       where teams.Contains(x.TeamId) && x.UserId != uid
                                       select x.UserId)
                    select fellowUsers).Distinct();
        }

        public class UpdateHolder {
            public UpdateHolder(int updateId, string entryId, int objectId, int origin, int target, DateTime timestamp) {
                UpdateId = updateId;
                EntryId = entryId;
                ObjectId = objectId;
                Origin = origin;
                Target = target;
                Timestamp = timestamp;
            }

            public UpdateHolder() { }

            public int UpdateId { get; set; }
            public string EntryId { get; set; }
            public int ObjectId { get; set; }
            public int Origin { get; set; }
            public int Target { get; set; }
            public DateTime Timestamp { get; set; }
        }
    }
}